
export default class FindP {
    
    // 地图尺寸
    map_size:number[]=[16,7];
    // 障碍物
    blocks:number[][]=[];
    // 开放列表
    openlist={};
    // 闭合列表
    closelist={};
     // # 当前处于的点
    curpoint='point1';
    // 最终的路径
    path:number[][]=[];




    // 判断一维数组是否在二维数组中
    listinclude(arr:number[][],ele:number[]):number{
        for(let i in arr){
            if(arr[i]+''==ele+''){
                // 在二维数组中返回索引
                return Number(i)
            }
        }
        // 不在二维数组中返回-1
        return -1
    }

    // # 获取位置的F值
    findF(nextpoint,destination){
        // 如果此点不在地图上,则不处理
        if(nextpoint[0]<1||nextpoint[0]>this.map_size[0]||nextpoint[1]<1||nextpoint[1]>this.map_size[1]){
            return
        }

        // # 如果此点为不可抵达点，则不处理
        for(let block of this.blocks){
            if (block+''==nextpoint+''){
                return}}
        // # 遍历开放列表
        for (let point in this.openlist){
            // # 如果此点在开放列表，则不处理
            if (this.openlist[point]['curpos']+'' == nextpoint+''){
                return}
        }
        for (let point in this.closelist){
            // # 如果此点在开放列表，则不处理
            if (this.closelist[point]['curpos']+'' == nextpoint+''){
                return}
    }
        let F = Math.abs((nextpoint[1] - this.closelist[this.curpoint]['curpos'][1])) + Math.abs(destination[0] - nextpoint[0]) + Math.abs(destination[1] - nextpoint[1]);
        // # 按当前点的个数增加名称后缀
        let key=Object.keys(this.openlist).length+Object.keys(this.closelist).length+1;
        this.openlist['point'+key] = {'F':F,'curpos': nextpoint, 'parent': this.curpoint};
    }




    getpath(start_point:number[],end_point:number[],blocks:number[][]){
    // 每次调用需要重置
    // 获取当前障碍物
    this.blocks=blocks;
    // 开放列表
    this.openlist={};
    // 闭合列表
    this.closelist={};
     // # 当前处于的点
    this.curpoint='point1';
    // 最终的路径
    this.path=[];
    // # 获取起点
    let start:number[]=start_point;
    // # 将起点加入闭合列表
    this.closelist['point1']={'curpos':start,'parent':'null'};
    // # 获取终点
    let destination=end_point;
    // 是否继续循环查找
    let Flag:boolean=true;



    while (Flag){
        // # 记录当前点周围所有点的F值
        // # 正上方
        let nextstep1=[this.closelist[this.curpoint]['curpos'][0],this.closelist[this.curpoint]['curpos'][1]+1];
        // # 正左方
        let nextstep3=[this.closelist[this.curpoint]['curpos'][0]-1,this.closelist[this.curpoint]['curpos'][1]];
        // # 正下方
        let nextstep5=[this.closelist[this.curpoint]['curpos'][0],this.closelist[this.curpoint]['curpos'][1]-1];
        // # 正右方
        let nextstep7=[this.closelist[this.curpoint]['curpos'][0]+1,this.closelist[this.curpoint]['curpos'][1]];
        // # 将周围点加入列表等待检索
        let steps=[nextstep1,nextstep3,nextstep5,nextstep7];

        // #遍历计算F值
        for (let step of steps){
            this.findF(step,destination)};
        // # 如果终点已在开放列表则反推路线
        for (let point in this.openlist){
            if (destination+'' == this.openlist[point]['curpos']+''){
                this.closelist[point]={'curpos': this.openlist[point]['curpos'], 'parent': this.openlist[point]['parent']};
                this.path.push(destination);
                // # 反推路径
                let findpath=point;
                while (this.closelist[findpath]['parent']!='null'){
                    let parent=this.closelist[findpath]['parent'];
                    this.path.push(this.closelist[parent]['curpos']);
                    findpath=parent;
                }
                Flag=false;
                // 倒推完成后反转
                this.path.reverse();
                // 获取到路径，退出查询
                return this.path;     
            }
        }

            
        if(Object.keys(this.openlist).length==0){
            console.log('未查询到路径');
            return this.path
        }
        else{

        // 将开放列表中第一个点的F值赋值给min
        let min=this.openlist[Object.keys(this.openlist)[0]]['F'];
        let minname='';
        for (let point in this.openlist){
            if (this.openlist[point]['F']<=min){
                min=this.openlist[point]['F'];
                minname=point;}
        }
        this.closelist[minname]={'curpos': this.openlist[minname]['curpos'], 'parent': this.openlist[minname]['parent']}
        delete this.openlist[minname];
        this.curpoint=minname;

        }
    
    }
    }







}
